package com.cskaoyan.javase.oop2.encapsulate._1extends._9override._0basic;

/**
 * 什么是方法的覆盖?
 *
 * 只要创建子类对象，调用test方法，无论这个调用是在子类中还是父类中,调用的结果都是子类中同名方法的执行结果。
 * 这就是方法的覆盖,它就和属性的隐藏不同了.
 *
 * 注意:
 *      1.方法只不过是内存中的一段二进制的指令合集,存储在方法区中各自类加载的区域内,它不存在被物理意义上覆盖
 *          父类中同名成员方法,仍然是可以被访问的
 *          通过在子类中"super."可以访问父类同名方法
 *      2.方法之所以体现出这种覆盖的特点,是因为"对象名.成员方法"的调用机制
 *          下面我们重点研究这种机制.
 *
 * 研究"对象名.成员方法"的调用机制
 * 对象名的由来,三种:
 *      1.父类引用指向父类对象
 *      2.子类引用指向子类对象
 *      3.父类引用指向子类对象
 * 调用机制研究的方向,两个:
 *      1."对象名.成员方法"的调用范围,能够调用哪些方法
 *      2."对象名.成员方法"的调用结果
 *
 * 首先,"对象名.成员方法"的调用范围仍然是引用决定的
 * 重点研究"对象名.成员方法"的调用结果
 *      1.父类引用指向父类对象
 *          调用结果是父类中方法的执行结果
 *      2.子类引用指向子类对象
 *          调用结果是子类中方法的执行结果
 *      3.父类引用指向子类对象
 *          调用结果是子类中方法的执行结果
 *
 * 以上,总结
 * "对象名.成员方法"的调用结果,需要等到程序执行
 * 根据对象的具体类型来确定,对象如果是子类类型
 * 即便是父类引用指向子类对象
 * 方法调用的结果仍然是子类中结果.
 *
 *
 * @since 16:00
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
       /* Son s = new Son();
        s.test();
        s.fatherInvokeTest();
        s.superInvokeTest();*/

       // 1.父类引用指向父类对象
        Father f = new Father();
        f.test();
        f.testFather();

        // 2.子类引用指向子类对象
        Son s = new Son();
        s.test();
        s.testSon();
        s.testFather();


        // 3.父类引用指向子类对象
        Father fs = new Son();
        fs.test();
        fs.testFather();
        // fs.testSon();

    }
}

class Father {
    public void test() {
        System.out.println("father");
    }
    // 父类独有的成员方法
    public void testFather(){
        System.out.println("father only");
    }
    // 方法的"Getter方法"
    public void fatherInvokeTest() {
        this.test();
    }
}

class Son extends Father {
    public void test() {
        System.out.println("son");
    }
    // 子类独有的成员方法
    public void testSon(){
        System.out.println("son only");
    }
    /*public void superInvokeTest() {
        super.test();
    }*/
}